%
% Filename:    ml605_fmc150_libgen.m
%
% Description: Creates a library containing all of the non-
%              memory mapped ports for the
%              ML605_FMC150
%

function ml605_fmc150_libgen()

disp('Loading the ''xbsTypes_r4'' library...');
load_system('xbsTypes_r4');

lib = ['ml605_fmc150_lib'];

disp(['Creating the ''' lib ''' library...']);
new_system(lib, 'Library');
open_system(lib);

name = 'CPU_RESET';
width = 1;
locs = '{''H10''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 20 100 50]);

name = 'GPIO_DIP_SW';
width = 8;
locs = '{''K21'',''K22'',''B18'',''C18'',''L20'',''L21'',''C22'',''D22''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 70 100 100]);

name = 'GPIO_SW_C';
width = 1;
locs = '{''G26''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 120 100 150]);

name = 'GPIO_SW_E';
width = 1;
locs = '{''G17''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 170 100 200]);

name = 'GPIO_SW_N';
width = 1;
locs = '{''A19''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 220 100 250]);

name = 'GPIO_SW_S';
width = 1;
locs = '{''A18''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 270 100 300]);

name = 'GPIO_SW_W';
width = 1;
locs = '{''H17''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 320 100 350]);

name = 'CLK_AB_N';
width = 1;
locs = '{''K27''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 370 100 400]);

name = 'CLK_AB_P';
width = 1;
locs = '{''K26''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 420 100 450]);

name = 'CHA_N';
width = 7;
locs = '{''H32'',''J34'',''H33'',''J29'',''J32'',''H30'',''E31''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 470 100 500]);

name = 'CHA_P';
width = 7;
locs = '{''G32'',''K33'',''H34'',''K28'',''J31'',''G31'',''F31''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 520 100 550]);

name = 'CHB_N';
width = 7;
locs = '{''B34'',''C34'',''E33'',''D32'',''G30'',''L26'',''K29''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 570 100 600]);

name = 'CHB_P';
width = 7;
locs = '{''C33'',''D34'',''E32'',''D31'',''F30'',''L25'',''J30''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 620 100 650]);

name = 'CLK_TO_FPGA_N';
width = 1;
locs = '{''B10''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 670 100 700]);

name = 'CLK_TO_FPGA_P';
width = 1;
locs = '{''A10''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 720 100 750]);

name = 'EXT_TRIGGER_N';
width = 1;
locs = '{''G33''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 770 100 800]);

name = 'EXT_TRIGGER_P';
width = 1;
locs = '{''F33''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 820 100 850]);

name = 'ADC_SDO';
width = 1;
locs = '{''C32''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 870 100 900]);

name = 'CDCE_SDO';
width = 1;
locs = '{''M27''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 920 100 950]);

name = 'PLL_STATUS';
width = 1;
locs = '{''K31''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 970 100 1000]);

name = 'DAC_SDO';
width = 1;
locs = '{''M33''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 1020 100 1050]);

name = 'MON_SDO';
width = 1;
locs = '{''N25''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 1070 100 1100]);

name = 'MON_N_INT';
width = 1;
locs = '{''M25''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 1120 100 1150]);

name = 'PRSNT_M2C_L';
width = 1;
locs = '{''AD9''}';
ss = add_input(lib, name, width, locs);
set_param(ss, 'Position', [20 1170 100 1200]);

name = 'GPIO_LED';
width = 8;
locs = '{''AD24'',''AE24'',''AG23'',''AB23'',''AE23'',''AE22'',''AC24'',''AC22''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 20 300 50]);

name = 'GPIO_LED_C';
width = 1;
locs = '{''AP24''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 70 300 100]);

name = 'GPIO_LED_E';
width = 1;
locs = '{''AE21''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 120 300 150]);

name = 'GPIO_LED_N';
width = 1;
locs = '{''AH27''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 170 300 200]);

name = 'GPIO_LED_S';
width = 1;
locs = '{''AH28''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 220 300 250]);

name = 'GPIO_LED_W';
width = 1;
locs = '{''AD21''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 270 300 300]);

name = 'DAC_DCLK_N';
width = 1;
locs = '{''T26''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 320 300 350]);

name = 'DAC_DCLK_P';
width = 1;
locs = '{''R26''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 370 300 400]);

name = 'DAC_DATA_N';
width = 8;
locs = '{''N29'',''L30'',''N30'',''R29'',''R27'',''P32'',''P30'',''M32''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 420 300 450]);

name = 'DAC_DATA_P';
width = 8;
locs = '{''N28'',''L29'',''M30'',''P29'',''R28'',''N32'',''P31'',''L33''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 470 300 500]);

name = 'DAC_FRAME_N';
width = 1;
locs = '{''P27''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 520 300 550]);

name = 'DAC_FRAME_P';
width = 1;
locs = '{''N27''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 570 300 600]);

name = 'TXENABLE';
width = 1;
locs = '{''B33''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 620 300 650]);

name = 'SPI_SCLK';
width = 1;
locs = '{''N34''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 670 300 700]);

name = 'SPI_SDATA';
width = 1;
locs = '{''P34''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 720 300 750]);

name = 'ADC_N_EN';
width = 1;
locs = '{''A33''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 770 300 800]);

name = 'ADC_RESET';
width = 1;
locs = '{''B32''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 820 300 850]);

name = 'CDCE_N_EN';
width = 1;
locs = '{''M26''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 870 300 900]);

name = 'CDCE_N_RESET';
width = 1;
locs = '{''M31''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 920 300 950]);

name = 'CDCE_N_PD';
width = 1;
locs = '{''L31''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 970 300 1000]);

name = 'REF_EN';
width = 1;
locs = '{''K32''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 1020 300 1050]);

name = 'DAC_N_EN';
width = 1;
locs = '{''N33''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 1070 300 1100]);

name = 'MON_N_EN';
width = 1;
locs = '{''R31''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 1120 300 1150]);

name = 'MON_N_RESET';
width = 1;
locs = '{''R32''}';
ss = add_output(lib, name, width, locs);
set_param(ss, 'Position', [220 1170 300 1200]);

return;

function ss = add_input(system, portname, width, locs)
disp(['Creating the ''' portname ''' input port...']);
ss = [system, '/' portname];
const = [ss '/Constant'];
port = [ss '/' portname];
out = [ss '/OutPort'];

% create the SubSystem
add_block('built-in/SubSystem', ss);

% create the internal components
add_block('built-in/Constant', const);
add_block('built-in/OutPort', out);

% create the actual port
add_block('xbsTypes_r4/Gateway In', port);
xlSetNonMemMap(port, 'Xilinx', 'jtaghwcosim');

% connect the internal components
add_line(ss, 'Constant/1', [portname '/1']);
add_line(ss, [portname '/1'], 'OutPort/1');

% configure the SubSystem
set_param(ss, 'ShowName', 'off');
set_param(ss, 'CopyFcn', 'set_param(gcb,''LinkStatus'',''inactive'');');
set_param(ss, 'Mask', 'on');
set_param(ss, 'MaskType', 'Non-Memory-Mapped Input Port');
set_param(ss, 'MaskSelfModifiable', 'on');
set_param(ss, 'MaskVariables', 'signed=@1;bpt=@2;show_in=@3;c=@4;');
set_param(ss, 'MaskPrompts', {'Signed  (2''s comp)';'Binary Point';'Provide Input Double';'Constant for Simulation'});
set_param(ss, 'MaskStyles', {'checkbox';'edit';'checkbox';'edit'});
set_param(ss, 'MaskValues', {'off';'0';'off';'0'});
callback = sprintf([ ...
    'mask_vis = get_param(gcb, ''MaskVisibilities'');\n' ...
    'if (strcmp(get_param(gcb, ''show_in''),''on''))\n' ...
    '    mask_vis(4) = {''off''};\n' ...
    'else\n' ...
    '    mask_vis(4) = {''on''};\n' ...
    'end\n' ...
    'set_param(gcb, ''MaskVisibilities'', mask_vis);\n' ...
    ]);
set_param(gcb, 'MaskCallbacks', {'';'';callback;''});
if (width == 1)
    set_param(ss, 'MaskVisibilities', {'off';'off';'on';'on'});
    set_param(ss, 'MaskDescription', sprintf([ ...
        'Port Name: "' portname '"\n' ...
        'Port Type: Boolean' ...
        ]));
    sign_test = '';
else
    set_param(ss, 'MaskDescription', sprintf([ ...
        'Port Name: "' portname '"\n' ...
        sprintf('Port Type: %d-bit Vector', width) ...
        ]));
    sign_test = sprintf([ ...
        'if (signed)\n' ...
        '    set_param([gcb ''/' portname '''],''arith_type'',''Signed  (2''''s comp)'');\n' ...
        'else\n' ...
        '    set_param([gcb ''/' portname '''],''arith_type'',''Unsigned'');\n' ...
        'end\n' ...
        ]);
end
set_param(ss, 'MaskDisplay', sprintf([ ...
    'patch([0 iWidth iWidth 0],[0 0 iHeight iHeight] , bg);\n' ...
    'patch(logoX,logoY, fg);\n' ...
    'plot([0 0 iWidth iWidth 0], [0 iHeight iHeight 0 0]);\n' ...
    'port_label(portdir,1,portstr);\n' ...
    'port_label(''output'',1,''' portname ''');\n' ...
    'text(2,5,''nmm'');\n' ...
    ]));
set_param(ss, 'MaskInitialization', sprintf([ ...
    '[bg,fg] = xlcmap(''IO'',0);\n' ...
    'iPos = get_param(gcb,''Position'');\n' ...
    'iWidth=iPos(3)-iPos(1);\n' ...
    'iHeight=iPos(4)-iPos(2);\n' ...
    '[logoX, logoY] = xlogo(iPos);\n' ...
    sign_test ...
    'if (show_in)\n' ...
    '    old = find_system(gcb, ''LookUnderMasks'', ''all'', ''Name'', ''Constant'');\n' ...
    '    if (length(old) > 0)\n' ...
    '        replace_block(gcb, ''Name'', ''Constant'', ''InPort'', ''noprompt'');\n' ...
    '        set_param([gcb ''/Constant''], ''Name'', ''InPort'');\n' ...
    '    end\n' ...
    '    portdir = ''input'';\n' ...
    '    portstr = ''dbl'';\n' ...
    'else\n' ...
    '    old = find_system(gcb, ''LookUnderMasks'', ''all'', ''Name'', ''InPort'');\n' ...
    '    if (length(old) > 0)\n' ...
    '        replace_block(gcb, ''Name'', ''InPort'', ''Constant'', ''noprompt'');\n' ...
    '        set_param([gcb ''/InPort''], ''Name'', ''Constant'');\n' ...
    '        set_param([gcb ''/Constant''], ''Value'', ''c'');\n' ...
    '    end\n' ...
    '    portdir = ''output'';\n' ...
    '    portstr = '''';\n' ...
    'end\n' ...
    ]));
set_param(ss, 'MaskIconFrame', 'off');

% configure the Constant
set_param(const, 'Position', [100 100 120 120]);
set_param(const, 'Value', 'c');

% configure the Gateway In
set_param(port, 'Position', [180 99 235 121]);
if (width == 1)
    set_param(port, 'arith_type', 'Boolean');
else
    set_param(port, 'arith_type', 'Unsigned');
    set_param(port, 'bin_pt', sprintf('max(0,min(bpt,%d))',width));
    set_param(port, 'n_bits', sprintf('%d', width));
end
set_param(port, 'LOCs', locs);
set_param(port, 'locs_specified', 'on');

% configure the OutPort
set_param(out, 'Position', [295 100 315 120]);

return;

function ss = add_output(system, portname, width, locs)
disp(['Creating the ''' portname ''' output port...']);
ss = [system, '/' portname];
in = [ss '/InPort'];
force = [ss '/Reinterpret'];
conv = [ss '/Convert'];
port = [ss '/' portname];
term = [ss '/Terminator'];

% create the SubSystem
add_block('built-in/SubSystem', ss);

% create the internal components
add_block('built-in/InPort', in);
if (width > 1)
    add_block('xbsTypes_r4/Reinterpret', force);
end
add_block('xbsTypes_r4/Convert', conv);
add_block('built-in/Terminator', term);

% create the actual port
add_block('xbsTypes_r4/Gateway Out', port);
xlSetNonMemMap(port, 'Xilinx', 'jtaghwcosim');

% connect the internal components
if (width > 1)
    add_line(ss, 'InPort/1', 'Reinterpret/1');
    add_line(ss, 'Reinterpret/1', 'Convert/1');
else
    add_line(ss, 'InPort/1', 'Convert/1');
end
add_line(ss, 'Convert/1', [portname '/1']);
add_line(ss, [portname '/1'], 'Terminator/1');

% configure the SubSystem
set_param(ss, 'ShowName', 'off');
set_param(ss, 'CopyFcn', 'set_param(gcb,''LinkStatus'',''inactive'');');
set_param(ss, 'Mask', 'on');
set_param(ss, 'MaskType', 'Non-Memory-Mapped Output Port');
set_param(ss, 'MaskSelfModifiable', 'on');
set_param(ss, 'MaskVariables', 'show_out=@1;');
set_param(ss, 'MaskPrompts', {'Provide Output Double'});
set_param(ss, 'MaskStyles', {'checkbox'});
set_param(ss, 'MaskValues', {'off'});
if (width == 1)
    set_param(ss, 'MaskDescription', sprintf([ ...
        'Port Name: "' portname '"\n' ...
        'Port Type: Boolean' ...
        ]));
else
    set_param(ss, 'MaskDescription', sprintf([ ...
        'Port Name: "' portname '"\n' ...
        sprintf('Port Type: %d-bit Vector', width) ...
        ]));
end
set_param(ss, 'MaskDisplay', sprintf([ ...
    'patch([0 iWidth iWidth 0],[0 0 iHeight iHeight] , bg);\n' ...
    'patch(logoX,logoY, fg);\n' ...
    'plot([0 0 iWidth iWidth 0], [0 iHeight iHeight 0 0]);\n' ...
    'port_label(portdir,1,portstr);\n' ...
    'port_label(''input'',1,''' portname ''');\n' ...
    'text(iWidth-10,5,''nmm'');\n' ...
    ]));
set_param(ss, 'MaskInitialization', sprintf([ ...
    '[bg,fg] = xlcmap(''IO'',0);\n' ...
    'iPos = get_param(gcb,''Position'');\n' ...
    'iWidth=iPos(3)-iPos(1);\n' ...
    'iHeight=iPos(4)-iPos(2);\n' ...
    '[logoX, logoY] = xlogo(iPos);\n' ...
    'if (show_out)\n' ...
    '    old = find_system(gcb, ''LookUnderMasks'', ''all'', ''Name'', ''Terminator'');\n' ...
    '    if (length(old) > 0)\n' ...
    '        replace_block(gcb, ''Name'', ''Terminator'', ''OutPort'', ''noprompt'');\n' ...
    '        set_param([gcb ''/Terminator''], ''Name'', ''OutPort'');\n' ...
    '    end\n' ...
    '    portdir = ''output'';\n' ...
    '    portstr = ''dbl'';\n' ...
    'else\n' ...
    '    old = find_system(gcb, ''LookUnderMasks'', ''all'', ''name'', ''OutPort'');\n' ...
    '    if (length(old) > 0)\n' ...
    '        replace_block(gcb, ''Name'', ''OutPort'', ''Terminator'', ''noprompt'');\n' ...
    '        set_param([gcb ''/OutPort''], ''Name'', ''Terminator'');\n' ...
    '    end\n' ...
    '    portdir = ''input'';\n' ...
    '    portstr = '''';\n' ...
    'end\n' ...
    ]));
set_param(ss, 'MaskIconFrame', 'off');

if (width > 1)
    % configure the InPort
    set_param(in, 'Position', [50 100 70 120]);

    % configure the Reinterpret
    set_param(force, 'Position', [130 94 170 126]);
else
    % configure the InPort
    set_param(in, 'Position', [150 100 170 120]);
end

% configure the Convert
set_param(conv, 'Position', [230 95 275 125]);
if (width == 1)
    set_param(conv, 'arith_type', 'Boolean');
else
    set_param(conv, 'arith_type', 'Unsigned');
    set_param(conv, 'bin_pt', sprintf('0',width));
    set_param(conv, 'n_bits', sprintf('%d', width));
end
set_param(port, 'LOCs', locs);
set_param(port, 'locs_specified', 'on');

% configure the Gateway Out
set_param(port, 'Position', [335 99 390 121]);

% configure the Terminator
set_param(term, 'Position', [450 100 470 120]);

return;
